package com.pictavore.image;

import java.awt.*;

/**
 *
 * @author dvenable
 */
public class TRC {

    static public int[] histogram(PVImage pvi)
    {
        if (pvi.NBits == 8)
            return histogram(pvi.sbuf8, pvi.Width, pvi.Height);
        else if (pvi.NBits == 16)
            return histogram(pvi.sbuf16, pvi.Width, pvi.Height);
        return null;

//        if (pvi.NBits == 8)
//            return histogram(pvi.buf8);
//        else if (pvi.NBits == 16 || pvi.NBits == 32)
//            return histogram(pvi.buf16);
//        return null;
    }
    static public int[] histogram(PVImage pvi, Rectangle win)
    {
        if (pvi.NBits == 8)
            return histogram(pvi.sbuf8, pvi.Width, pvi.Height, win);
        else if (pvi.NBits == 16)
            return histogram(pvi.sbuf16, pvi.Width, pvi.Height, win);
        return null;
//        if (pvi.NBits == 8)
//            return histogram(pvi.buf8, pvi.Width, pvi.Height, win);
//        else if (pvi.NBits == 16 || pvi.NBits == 32)
//            return histogram(pvi.buf16, pvi.Width, pvi.Height, win);
//        return null;
    }


    // <editor-fold defaultstate="collapsed" desc="full frame histograms">
    static public int[] histogram(byte[] img, int w, int h)
    {
        int len = w*h;
        if (img.length < len)
            len = img.length;

        int px = 0;
        int[] hst = new int[256];
        for (int k = 0; k < len; ++k)
        {
            px = (img[k] & 0x00ff);
            hst[px]++;

        }
        return hst;
    }

    static public int[] histogram(short[] img, int w, int h)
    {
        int len = w*h;
        if (img.length < len)
            len = img.length;

        int px = 0;
        int[] hst = new int[65536];
        for (int k = 0; k < len; ++k)
        {
            px = (img[k] & 0x0000ffff);
            hst[px]++;
        }
        return hst;
    }
    // </editor-fold>

// <editor-fold defaultstate="collapsed" desc="int-based histograms - depracated">
//    static public int[] histogram(int[] dta, int nbits)
//    {
//        int[] hst = (nbits == 8) ? new int[256] : new int[65536];
//        if (nbits == 8)
//        {
//            for (int k = 0; k < dta.length; ++k)
//            {
//                int px = dta[k] & 0x00ff;
//                hst[px]++;
//            }
//        } else if (nbits == 16)
//        {
//            for (int k = 0; k < dta.length; ++k)
//            {
//                int px = dta[k] & 0x0000ffff;
//                hst[px]++;
//            }
//        }
//        return hst;
//    }
//
//    static public int[] histogram(int[] dta, int nbits, int w, int h, Rectangle win)
//    {
//        int[] hst = (nbits == 8) ? new int[256] : new int[65536];
//
//        int ofs = win.y * w + win.x;
//
//        if (nbits == 8)
//        {
//            for (int y = 0; y < win.height; ++y, ofs += w)
//            {
//                for (int x = 0; x < win.width; ++x)
//                {
//                    int px = dta[ofs + x] & 0x00ff;
//                    hst[px]++;
//                }
//
//            }
//        } else if (nbits == 16)
//        {
//            for (int y = 0; y < win.height; ++y, ofs += w)
//            {
//                for (int x = 0; x < win.width; ++x)
//                {
//                    int px = dta[ofs + x] & 0x0000ffff;
//                    hst[px]++;
//                }
//
//            }
//        }
//        return hst;
//    }
// </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="buffer histogram">
    static public int[] histogram(short[] img, int w, int h, Rectangle win)
    {
        int[] hst = new int[65536];

        int px = 0;
        int ofs = win.y * w + win.x;
        for (int y = 0; y < win.height; ++y, ofs += w)
        {
            for (int x = 0; x < win.width; ++x)
            {
                px = img[ofs + x] & 0x0000ffff;
                hst[px]++;
            }

        }
        return hst;
    }

    static public int[] histogram(byte[] img, int w, int h, Rectangle win)
    {
        int[] hst = new int[256];

        int px = 0;
        int ofs = win.y * w + win.x;
        for (int y = 0; y < win.height; ++y, ofs += w)
        {
            for (int x = 0; x < win.width; ++x)
            {
                px = (img[ofs + x] & 0x00ff);
                hst[px]++;
            }

        }
        return hst;
    }

    // </editor-fold>

    static public int[] equalizeTRC(int[] hst, int nbits)
    {
        int max = (1<<nbits) - 1;

        int npix = 0;
        for (int k=0; k<=max; ++k)
            npix += hst[k];

        int[] trc = new int[max+1];

        long rsum = 0;      // running sum of histogram
        for( int i = 0 ; i <= max ; i++ )
        {
            rsum += hst[i];
            trc[i] = (int)(max * rsum / npix);
        }

        return trc;
    }

    static public int[] stretchTRC(int[] hst, int nbits)
    {
        int min = 0;
        int max = hst.length;
        for (int k=0; k<hst.length; ++k)
            if (hst[k] > 0)
            { min = k; break; }

        for (int k=hst.length-1; k>=0; k--)
            if (hst[k] > 0)
            { max = k; break; }
        return stretchTRC(min, max, nbits);
    }

    static public int[] stretchTRC(int mn, int mx, int nbits)
    {
        int max = (1<<nbits) - 1;
        int[] trc = new int[max+1];

        for (int k=0; k<mn; ++k)
            trc[k] = 0;
        for (int k=mn; k<mx; ++k)
            trc[k] = max * (k-mn) / (mx-mn);
        for (int k=mx+1; k<=max; ++k)
            trc[k] = max;

        return trc;
    }

    static public int[] piecewiseTRC(Point[] knots, int nbits)
    {
        int max = (1<<nbits) - 1;
        int[] trc = new int[max+1];

        int sx = 0;
        int sy = 0;
        for (Point p : knots)
        {
            int ex = (int)p.getX();
            int ey = (int)p.getY();

            if (ey==sy)
                for (int x = sx; x<ex; ++x)
                    trc[x] = sy;
            else
            {
                double sf = (ey-sy) / (ex-sx);
                for (int x = sx; x<ex; ++x)
                    trc[x] = sy + (int)(((double)(x-sx))*sf + 0.5);
            }

            sx = ex;
            sy = ey;
        }
        return trc;
    }

    static public int[] powerTRC(double p1, double p2, int nbits)
    {
        return null;
    }

}
